package com.gopay.bis.web.controller.gobank;

import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gopay.remote.cashier.bis.CashierBgNotifyRemoteService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.gopay.bis.common.util.IpAddrUtil;
import com.gopay.bis.domain.order.OrderInfo;
import com.gopay.bis.service.bank.BankIntrChannConfService;
import com.gopay.bis.service.bank.BankIntrChannConfService.OutStlmTranCode;
import com.gopay.bis.service.bank.go.GoBankService;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.SpdbConstants;
import com.gopay.common.constants.bank.UmPayConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.MtPayBaseMessage;
import com.gopay.common.domain.bis.BaseBisBankConfig;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.proccode.ProcCodeInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.proccode.DicProcCodeService;
import com.gopay.common.util.HttpTransport;
import com.gopay.common.util.RequestUtils;
import com.gopay.remote.bank.BankInteractRemoteService;
import com.gopay.remote.bank.MtPayInteractRemoteService;

@Controller
@Scope("prototype")
public class MtPayGoBankController {
	private static Logger logger = LoggerFactory
			.getLogger(MtPayGoBankController.class);

	@Resource(name = "goBankService")
	private GoBankService goBankService;

	@Resource(name = "bankIntrChannConfService")
	private BankIntrChannConfService bankIntrChannConfService;

	@Resource(name = "mtPaybankInteractService")
	private MtPayInteractRemoteService mtPaybankInteractService;

	@Resource(name = "dicProcCodeService")
	private DicProcCodeService dicProcCodeService;

	@Resource(name = "notifyCashier")
	private HttpTransport notifyCashier;

	@Resource(name = "cashierBgNotifyRemoteService")
	private CashierBgNotifyRemoteService cashierBgNotifyRemoteService;

	@Resource(name = "bisConfig")
	protected Map<String, String> bisConfig;

	/**
	 * 跳转银行
	 * 
	 * @param HttpServletRequest
	 * @param HttpServletResponse
	 * @return ModelAndView
	 */
	@RequestMapping(value = "/mtPayGoBank", method = { RequestMethod.POST })
	protected ModelAndView execute(HttpServletRequest request,HttpServletResponse response) {
		String notifyUrl = bisConfig.get("BIS.CLIENT.NOTIFY.CASHIER.BANK.RES");
		String viewName = bisConfig.get("BIS.MTPAT.NOTIFY.CASHIER.FORWARD");
		logger.error("--------------- GoBankController  ---------------");
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		// 打印请求参数
		displayRequestParameters(request);

		ModelAndView model = new ModelAndView();

		try {
			
			checkRequest(request);

			// 订单号
			String orderId = request.getParameter("orderId");
			// 银行业务产品
			String bankBusProd = request.getParameter("bankBusProd");
			
			// 手机号
			String phoneNo = request.getParameter("phoneNo");
			//持卡人姓名
			String cardHolder = request.getParameter("cardHolder");
			// 卡号
			String cardNo = request.getParameter("cardNo");
			String cvv2 = request.getParameter("cvv2");
			String availableDate = request.getParameter("availableDate");
			String bank = request.getParameter("bank");
			String cidNo = request.getParameter("cidNo");
			String cidType = request.getParameter("cidType");
			BisBankBusinessProd bankBusProdEnum = BisBankBusinessProd.get(bankBusProd);
			// 持卡人IP地址
			String ip = IpAddrUtil.getRemoteRealIpAddr(request);
			// 消息对象
			BaseMessage base = goBankService.buildSign(orderId,RequestUtils.getRemoteRealIpAddr(request));
			base.setBankBusProd(bankBusProdEnum);

			// 获取银行接口通道配置信息
			BaseBisBankExtConfig bankConfig = bankIntrChannConfService.findBaseBisBankExtConfig(base.getBankBusProd(), base.getBank());
			// 校验银行业务产品是否支持该通道
			checkBankBussProdAndIntrChan(bankConfig, bankBusProd);
			// 校验通道信息
			checkBankIntrChan(bankConfig, OutStlmTranCode._1000);

			// 平台外部清算机构代码
			String outStlmCd = InitialSpringBeanName.getOutStlmCd(bankConfig.getChCode(), bankBusProd, base.getBank());
			String intrfaceBankCode = bankConfig.getIntrfaceBankCode();
			if (StringUtils.isBlank(intrfaceBankCode)) {
				intrfaceBankCode = base.getBank();
			}
			
			base.setBankIntrChann(BisBankInterfaceChannel.get(bankConfig.getChCode()));
			base.setSpecial(ip);
			base.setOutStlmCd(outStlmCd);
			MtPayBaseMessage mtPayMsg = new MtPayBaseMessage();
			//设置无卡支付信息
			BeanUtils.copyProperties(base, mtPayMsg);
			mtPayMsg.setMediaId(phoneNo);
			mtPayMsg.setCardHolder(cardHolder);
			mtPayMsg.setCardNo(cardNo);
			mtPayMsg.setCvv2(cvv2);
			String m  = availableDate.substring(0,2);
			String y = availableDate.substring(2,4);
			mtPayMsg.setAvailableDate(y+m);
			mtPayMsg.setIdentityType("IDENTITY_CARD");
			mtPayMsg.setIdentityCode(cidNo);
			
			
			Result result = mtPaybankInteractService.pay(mtPayMsg);
			// 银行报文加密并组装
						if(bank.equals("TBANK")){
							Map<String, String> param = new HashMap<String, String>();
								// 验签成功入账
								param.put("orderId",orderId);
								param.put("amt", base.getAmount().toString());
								param.put("cardType", "Unknown");
								param.put("notifyNum", "1");
								param.put("payStatus", "00");
								param.put("retCode", "00");
								param.put("retMsg", "验签成功");
								param.put("signData", "");
								param.put("isFront", base.isFront()+"");
							/*notifyCashier.submit(param);*/ //生产优化10期 lx 2017-9-30 16:23:37
							cashierBgNotifyRemoteService.callBgNotify(param);
							
							model.setViewName(viewName);
							 OrderInfo orderInfo = new OrderInfo();
							orderInfo.setOrderId(orderId);
					         orderInfo.setAmt(base.getAmount().toString());
					         orderInfo.setNotifyNum("1");
						        orderInfo.setPayStatus("00");
						        orderInfo.setRetCode("00");
						        orderInfo.setRetMsg("");
							model.addObject("notifyUrl", notifyUrl);
							model.addObject("orderInfo", orderInfo);
							model.addObject("outStlmCd", outStlmCd);// 平台外部清算机构代码
							model.addObject("bankCode", base.getBank());// 接口银行码
							
							model.setViewName(bisConfig.get("BIS.MTPAT.NOTIFY.CASHIER.FORWARD.FAIl"));// 页面
							return model;
						}
			if (!result.isSuccess()) {// 处理失败
				throw new GopayException(result.getResultCode());
			}
			OrderInfo orderInfo = new OrderInfo();
			if((boolean) result.getModel("flag")){
				 
					orderInfo.setOrderId(orderId);
			         orderInfo.setAmt(base.getAmount().toString());
			         orderInfo.setNotifyNum("1");
				      orderInfo.setPayStatus("00");
				     orderInfo.setRetCode("00");
				     orderInfo.setRetMsg("");
				     model.setViewName(viewName);
			}else{
				orderInfo.setOrderId(orderId);
		         orderInfo.setAmt(base.getAmount().toString());
		         orderInfo.setNotifyNum("1");
			      orderInfo.setPayStatus("01");
			     orderInfo.setRetCode("00");
			     orderInfo.setRetMsg("");
			     model.setViewName(bisConfig.get("BIS.MTPAT.NOTIFY.CASHIER.FORWARD.FAIl"));// 页面
			}
			model.addObject("notifyUrl", notifyUrl);
			model.addObject("orderInfo", orderInfo);
			model.addObject("outStlmCd", outStlmCd);// 平台外部清算机构代码
			model.addObject("bankCode", base.getBank());// 接口银行码
			
			model.addObject("message", result.getDefaultModel());// 清算机构消息对象
			

		} catch (GopayException e) {
			logger.error("GoBankController GopayException", e);
			ProcCodeInfo procCodeInfo = dicProcCodeService.getProcCodeInfo(e.getErrCode());
			model.addObject("errorCode", e.getErrCode());
			model.addObject("errorMsg", procCodeInfo.getMessage());
			model.setViewName("screen/error");
		} catch (Exception e) {
			logger.error("GoBankController Exception", e);
			model.addObject("errorCode", ProcCodeConstants.PROC_CODE_100F1002);
			model.addObject("errorMsg", e.getMessage());
			model.setViewName("screen/error");
		}
		return model;
	}

	/**
	 * logger
	 * 
	 * @param HttpServletRequest
	 */
	@SuppressWarnings("rawtypes")
	private void displayRequestParameters(HttpServletRequest request) {
		for (Enumeration enumeration = request.getParameterNames(); enumeration
				.hasMoreElements();) {
			String eleName = (String) enumeration.nextElement();
			String eleValue = request.getParameter(eleName);
			logger.error("收到的请求参数键: [" + eleName + "]，值: [" + eleValue + "]");
		}
	}

	/**
	 * 
	 * @param BisBankBusinessProd
	 * @return String
	 * @throws GopayException
	 */
	private String getViewName(BisBankBusinessProd bankBusProdEnum)
			throws GopayException {
		if (BisBankBusinessProd._05.equals(bankBusProdEnum)) {
			return "screen/mtpay/submit";
		}
		logger.error("暂不支持的银行业务产品：" + bankBusProdEnum);
		throw new GopayException(ProcCodeConstants.PROC_CODE_100E7014);
	}

	/**
	 * 校验银行业务产品是否支持该通道
	 * 
	 * @param config
	 * @param bankBusProdEnum
	 * @throws GopayException
	 */
	private void checkBankBussProdAndIntrChan(BaseBisBankExtConfig config,
			String bankBusProd) throws GopayException {
		if (null == config) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7021);
		}
		String intrChann = config.getChCode();// 接口通道
		bankIntrChannConfService.checkBankBussProdAndIntrChan(intrChann,
				bankBusProd);
	}

	/**
	 * 校验银行通道信息
	 * 
	 * @param BaseBisBankConfig
	 * @param OutStlmTranCode
	 * @throws GopayException
	 */
	private void checkBankIntrChan(BaseBisBankConfig config,
			OutStlmTranCode outTranCode) throws GopayException {
		bankIntrChannConfService.checkBankIntrChan(config, outTranCode);
	}

	/**
	 * 
	 * @param HttpServletRequest
	 * @throws GopayException
	 * 
	 */
	private void checkRequest(HttpServletRequest request) throws GopayException {
		String orderId = request.getParameter("orderId");
		String bankBusProd = request.getParameter("bankBusProd");
		String phoneNo = request.getParameter("phoneNo");
		String cardHolder = request.getParameter("cardHolder");
		String cardNo = request.getParameter("cardNo");
		String cvv2 = request.getParameter("cvv2");
		String availableDate = request.getParameter("availableDate");
		String bank = request.getParameter("bank");
		String cidNo = request.getParameter("cidNo");
		String cidType = request.getParameter("cidType");
		logger.error("-----------orderId----------------" + orderId);
		logger.error("-----------bankBusProd----------------" + bankBusProd);
		if (StringUtils.isBlank(orderId)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1089);
		}
		if (StringUtils.isBlank(bankBusProd)
				|| !BisBankBusinessProd._05.value.equals(bankBusProd)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E7014);
		}
		if (StringUtils.isBlank(phoneNo)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6073);
		}
		if (StringUtils.isBlank(cardHolder)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6072);
		}
		if (StringUtils.isBlank(cardNo)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6069);
		}
		if (StringUtils.isBlank(cvv2)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6070);
		}
		if (StringUtils.isBlank(availableDate)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6071);
		}
		if (StringUtils.isBlank(bank)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1135);
		}
		if (StringUtils.isBlank(cidNo)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6075);
		}
		if (StringUtils.isBlank(cidType)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6074);
		}
	}
}
